package com.szh.gulimall.ware.listener;

import com.rabbitmq.client.Channel;
import com.szh.common.dto.mq.OrderTo;
import com.szh.common.dto.mq.StockLockTo;
import com.szh.gulimall.ware.service.WareSkuService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;

/**
 * @author: SongZiHao
 * @date: 2023/2/6
 */
@Service
public class StockReleaseListener {

    private static final Logger LOGGER = LoggerFactory.getLogger(StockReleaseListener.class);

    @Autowired
    private WareSkuService wareSkuService;

    /**
     * 库存解锁1: 只有订单不存在或者状态是超时未支付（已取消），才可以解锁库存
     */
    @RabbitHandler
    @RabbitListener(queues = "stock.release.stock.queue")
    public void handleStockLockedRelease(StockLockTo to, Message message, Channel channel) throws IOException {
        try {
            LOGGER.info("收到解锁库存的消息....");
            //库存解锁
            wareSkuService.unlockStock(to);
            //之后手动确认消息，将死信队列中的消息删掉
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception ex) { //远程调用失败了，将消息拒绝之后重新放回队列，让别人继续解锁库存
            channel.basicReject(message.getMessageProperties().getDeliveryTag(), true);
        }
    }

    /**
     * 库存解锁2: 订单服务由于网络等原因卡顿，导致库存服务先查询了订单状态，而此时订单是新建状态，还没有超时，所以库存服务不会解锁卡顿订单的库存
     *           之后订单服务才缓过劲，此时订单超时，但库存服务已经执行完毕，导致这个卡顿的订单对应的库存永远无法解锁
     */
    @RabbitHandler
    @RabbitListener(queues = "stock.release.stock.queue")
    public void handleOrderClockRelease(OrderTo orderTo, Message message, Channel channel) throws IOException {
        try {
            LOGGER.info("收到解锁库存的消息....");
            //库存解锁
            wareSkuService.unlockStock(orderTo);
            //之后手动确认消息，将死信队列中的消息删掉
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception ex) { //远程调用失败了，将消息拒绝之后重新放回队列，让别人继续解锁库存
            channel.basicReject(message.getMessageProperties().getDeliveryTag(), true);
        }
    }
}
